use std::cell::RefCell;
use std::rc::Rc;
use gloo::timers::callback::Timeout;
use web_sys::{Element};
use yew::{classes, html, use_node_ref, AppHandle, Callback, Component, Context, ContextHandle, Html, NodeRef, Properties, UseStateHandle};
use yew::platform::spawn_local;
use yew_router::prelude::RouterScopeExt;
use crate::db::pojo::pojo::{ImMessage, ImSession};
use crate::business::app_state::AppState;
use crate::business::component::im_trait::{Render};
use crate::business::im_router::ImRoute;
use crate::business::component::list_view::{ListMsg, ListProps, ListView};
use crate::business::page::fragment::message_control_view::MessageControlView;
use crate::business::page::fragment::message_editor_view::MessageEditorView;
use crate::business::page::fragment::message_item_view::MessageItemView;
use crate::business::service::message_read_service::{MessageReadData, MessageReadService};
use crate::business::websocket::receive_send_handle::{ImReceiveSendActionMessage, ImReceiveSendHandleMsg};
use crate::db::service::im_message_service::ImMessageService;

#[derive(Properties, Clone)]
pub struct MessageListViewProps {
    pub select_session: Option<Rc<RefCell<ImSession>>>,
    pub count: usize,
    pub message_read_handle: UseStateHandle<MessageReadService>,
}

impl PartialEq for MessageListViewProps {
    fn eq(&self, other: &Self) -> bool {
        self.select_session == other.select_session && self.count == other.count
    }
}

pub struct MessageListView {
    init_data: Vec<ImMessage>,
    div_ref: NodeRef,
    state: AppState,
    _listener: ContextHandle<AppState>,
    list_handle: Rc<RefCell<Option<AppHandle<ListView<ImMessage>>>>>,
}

pub enum MessageListViewMsg {
    ContextChanged(AppState),
    AddNewMessage(ImMessage),
    AddNewMessages(Vec<ImMessage>),
    AddOldMessage(ImMessage),
    ActionMessage(ImReceiveSendActionMessage),
    Refresh,
}

impl Component for MessageListView {
    type Message = MessageListViewMsg;
    type Properties = MessageListViewProps;

    fn create(ctx: &Context<Self>) -> Self {
        log::trace!("create message session: {:?}", ctx.props().select_session);
        let data_list = vec![];

        let (state, _listener) = ctx
            .link()
            .context::<AppState>(ctx.link().callback(MessageListViewMsg::ContextChanged))
            .expect("context to be set");

        let state2 : AppState = state.clone();
        let callback = ctx.link().callback(MessageListViewMsg::ActionMessage);

        let receive_send_handle = state2.receive_send_handle.clone();
        if let Some(receive_send_handle) = receive_send_handle {
            receive_send_handle.dispatch(ImReceiveSendHandleMsg::ActionMessageCallback(callback));
        } else {
            let navigator = ctx.link().navigator();
            if let Some(navigator) = navigator {
                navigator.push(&ImRoute::ToLogin);
            }
        }

        // load_data(state2, ctx);

        MessageListView{init_data: data_list, div_ref: NodeRef::default(), state, _listener, list_handle: Rc::new(RefCell::new(None)) }
    }

    fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
        match msg {
            MessageListViewMsg::ContextChanged(state) => {
                self.state = state;
                true
            }
            MessageListViewMsg::AddNewMessage(msg) => {
                log::info!("show message22: {:?}", msg);
                let message_read_data = MessageReadData::from(&msg);

                if let Some(list_handle) = self.list_handle.borrow().as_ref() {
                    list_handle.send_message(ListMsg::AddLastData(msg));
                }

                let user_id = ctx.props().select_session.clone().unwrap().borrow().current_user_id.clone();
                let message_read_service = ctx.props().message_read_handle.clone();
                time_out(600, user_id, message_read_service, vec![message_read_data]);
                true
            }
            MessageListViewMsg::AddNewMessages(msgs) => {
                log::info!("show message22: {:?}", msgs);

                let message_read_data_list = msgs.iter().map(|message| {
                    let message_read_data = MessageReadData::from(message);
                    message_read_data
                }).collect::<Vec<_>>();
                if let Some(list_handle) = self.list_handle.borrow().as_ref() {
                    list_handle.send_message(ListMsg::AddLastDataList(msgs));
                }

                let user_id = ctx.props().select_session.clone().unwrap().borrow().current_user_id.clone();
                let message_read_service = ctx.props().message_read_handle.clone();
                time_out(600, user_id, message_read_service, message_read_data_list);
                true
            }
            MessageListViewMsg::AddOldMessage(msg) => {
                log::info!("show message22: {:?}", msg);
                if let Some(list_handle) = self.list_handle.borrow().as_ref() {
                    list_handle.send_message(ListMsg::AddFirstData(msg));
                }
                true
            }
            MessageListViewMsg::ActionMessage(msg) => {
                log::info!("show message22: {:?}", msg);
                let select_session = ctx.props().select_session.clone();
                if select_session.is_none() {
                    return false;
                }
                let select_session_id = select_session.unwrap().borrow().id.unwrap();
                if let Some(list_handle) = self.list_handle.borrow().as_ref() {
                    match msg {
                        ImReceiveSendActionMessage::Show(messages) => {
                            let message_list = messages.into_iter().filter(|message| message.session_id == select_session_id).collect::<Vec<ImMessage>>();
                            let message_read_data_list = message_list.iter().map(|message| MessageReadData::from(message)).collect::<Vec<_>>();
                            if message_list.len() > 0 {
                                list_handle.send_message(ListMsg::AddLastDataList(message_list));

                                let user_id = ctx.props().select_session.clone().unwrap().borrow().current_user_id.clone();
                                let message_read_service = ctx.props().message_read_handle.clone();
                                time_out(600, user_id, message_read_service, message_read_data_list);
                            }
                        }
                        ImReceiveSendActionMessage::Update(messages) => {
                            let message_list = messages.into_iter().filter(|message| message.session_id == select_session_id).collect::<Vec<ImMessage>>();
                            if message_list.len() > 0 {
                                list_handle.send_message(ListMsg::UpdateDataList(message_list));
                            }
                        }
                    }
                }
                true
            }
            MessageListViewMsg::Refresh => {
                log::info!("refresh clean");
                if let Some(list_handle) = self.list_handle.borrow().as_ref() {
                    list_handle.send_message(ListMsg::Clean);
                }
                true
            }
        }
    }

    fn changed(&mut self, ctx: &Context<Self>, old_props: &Self::Properties) -> bool {
        if let Some(list_handle) = self.list_handle.borrow().as_ref() {
            list_handle.send_message(ListMsg::Clean);
        }
        if ctx.props().select_session.is_some()  {
            if old_props.select_session.is_none() {
                let select_session2 = ctx.props().clone().select_session.unwrap();
                let session_id = &select_session2.borrow().id;
                load_data(session_id.clone().unwrap(), ctx);
            } else {
                let session = ctx.props().select_session.clone().unwrap();
                let old_session = old_props.select_session.clone().unwrap();
                if session != old_session {
                    let select_session = ctx.props().clone().select_session.unwrap();
                    let session_id = &select_session.borrow().id;
                    load_data(session_id.clone().unwrap(), ctx);
                }
            }
        }
        true
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        let div_ref = self.div_ref.clone();
        let call_back = Callback::from(move |_| {
            if let Some(window) = web_sys::window() {
                if let Some(document) = window.document() {
                    // 查找所有关闭按钮并触发点击
                    if let Some(element) = document.get_element_by_id("item_200") {
                        element.scroll_into_view();
                    }
                }
            }
        });

        let title = match ctx.props().select_session.clone() {
            Some(s) => s.borrow().name.clone(),
            None => "".to_ascii_lowercase(),
        };

        let select_session = ctx.props().clone().select_session;
        // let select_message = use_state(|| None);

        let scope = ctx.link().clone();
        let show_message_callback = Callback::from(move |messages: Vec<ImMessage>| {
            scope.send_message(MessageListViewMsg::AddNewMessages(messages));
        });

        let show_class = if select_session.is_some() { "show" } else { "hidden"};
        html! {
            <div class={classes!("message-container", show_class)}>
                <div class="message-header">
                    <label>{title}</label>
                    <label class="row-expanded"> </label>
                    // <label onclick={ call_back }> {"scroll"} </label>
                    <img src="/imgs/more.png" onclick={ call_back }/>
                </div>

                <div class="message-list-view" ref={ div_ref }></div>

                <MessageControlView/>

                <MessageEditorView session = {select_session} ref_message = {None} {show_message_callback}/>
            </div>
        }
    }

    fn rendered(&mut self, _ctx: &Context<Self>, first_render: bool) {
        let div_ref = self.div_ref.clone();
        let data = self.init_data.clone();
        if first_render {
            let div = div_ref
                .cast::<Element>()
                .expect("div_ref not attached to div element");

            let list_props = ListProps::new(15);
            let list_app_handle = yew::Renderer::<ListView<ImMessage>>::with_root_and_props(div, list_props).render();
            let list_app_handle2 = list_app_handle.clone();
            self.list_handle.borrow_mut().replace(list_app_handle);
            list_app_handle2.send_message(ListMsg::Set(data));
        }
    }

    fn destroy(&mut self, _ctx: &Context<Self>) {
        let state2 : AppState = self.state.clone();
        let websocket_handle = state2.receive_send_handle;
        if let Some(websocket_handle) = websocket_handle {
            websocket_handle.dispatch(ImReceiveSendHandleMsg::RemoveMessageCallback);
        }
        log::info!("remove message callback");
    }
}

fn time_out(timeout: u32, user_id: String, message_read_service: UseStateHandle<MessageReadService>, message_read_data_list: Vec<MessageReadData>) {
    Timeout::new(timeout, move || {
        let message_read_service_clone = message_read_service.clone();
        spawn_local(async move {
            message_read_service_clone.async_handle_read(user_id, message_read_data_list).await;
        });
    }).forget();
}

fn load_data(session_id: u64, ctx: &Context<MessageListView>) {
    let message_service = ImMessageService;
    let message_list = message_service.query_messages_by_session_id(session_id, None, 500);
    // log::info!("load message list: {:?}", message_list);
    let link = ctx.link().clone();
    link.send_message(MessageListViewMsg::AddNewMessages(message_list));
}

impl Render for ImMessage {

    fn render(&self) -> Html {
        html! {
            <MessageItemView message = {self.clone()} />
        }
    }
}